package cn.w.outdoor.lib.common;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;

public class TimeCountDownTools {

    private final static TimeCountDownTools instance = new TimeCountDownTools();

    private TimeCountDownTools() {
        startTimeCountDownTools();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                stopTimeCountDownTools();
            }
        });
    }

    public static TimeCountDownTools getInstance() {
        return instance;
    }

    private final AtomicBoolean control = new AtomicBoolean(false);
    private TimeCountDownThread timeCountDownThread = null;

    private void startTimeCountDownTools() {
        synchronized (control) {
            if (!control.get()) {
                if (timeCountDownThread == null) {
                    timeCountDownThread = new TimeCountDownThread();
                    timeCountDownThread.start();
                    control.set(true);
                }
            }
        }
    }

    private void stopTimeCountDownTools() {
        synchronized (control) {
            if (control.get()) {
                if (timeCountDownThread != null) {
                    timeCountDownThread.stopThread();
                    try {
                        timeCountDownThread.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    timeCountDownThread = null;
                    control.set(false);
                }
            }
        }
    }

    public void addTimeCountDownUnit(TimeCountDownUnit timeCountDownUnit) {
        if (timeCountDownUnit == null) return;
        if (timeCountDownThread != null) {
            timeCountDownThread.addTimeCountDownUnit(timeCountDownUnit);
        }
    }

    private class TimeCountDownThread extends Thread {

        private final Queue<TimeCountDownUnit> timeCountDownUnitQueue = new ConcurrentLinkedQueue<>();

        public void addTimeCountDownUnit(TimeCountDownUnit timeCountDownUnit) {
            if (timeCountDownUnit == null) return;
            synchronized (timeCountDownUnitQueue) {
                timeCountDownUnitQueue.offer(timeCountDownUnit);
            }
        }

        private boolean isStopThread = false;

        public void stopThread() {
            this.isStopThread = true;
        }

        @Override
        public void run() {
            isStopThread = false;
            while (!isStopThread) {

                long timeStamp = System.currentTimeMillis();
                synchronized (timeCountDownUnitQueue) {
                    int queueSize = timeCountDownUnitQueue.size();
                    while (/* 查看队列中是否还包含其他的指令 */timeCountDownUnitQueue.peek() != null &&
                            /* 防止在一次循环中间多次执行 */queueSize > 0) {
                        queueSize--;
                        TimeCountDownUnit timeCountDownUnit = timeCountDownUnitQueue.poll();
                        timeCountDownUnit.setWaitTimeLimit(timeCountDownUnit.getWaitTimeLimit() - 1);
                        timeCountDownUnit.action(timeCountDownUnit.getWaitTimeLimit());
                        if (!(timeCountDownUnit.isStopCountDown() || timeCountDownUnit.getWaitTimeLimit() == 0)) {
                            timeCountDownUnitQueue.offer(timeCountDownUnit);
                        }
                    }
                }
                long sleepTime = 1000 - (System.currentTimeMillis() - timeStamp);
                if (sleepTime > 0) {
                    try {
                        Thread.sleep(sleepTime);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }

}
